import { TimelineLayoutCalculator } from './TimelineLayoutCalculator'
import { ViewportState, SceneBlockData, DragState } from './types'

/**
 * 时间线交互处理器
 * 处理鼠标事件和拖拽操作
 */
export class TimelineInteractionHandler {
  private layoutCalculator: TimelineLayoutCalculator
  private onSceneSelect: (sceneId: string | null) => void
  private onSceneReorder: (fromIndex: number, toIndex: number) => void
  private setDragState: (state: DragState) => void

  private viewport: ViewportState = { scale: 1, offsetX: 0, width: 0, height: 0, totalDuration: 0 }
  private sceneBlocks: SceneBlockData[] = []
  private isMouseDown = false
  private dragStartPosition = { x: 0, y: 0 }
  private dragThreshold = 5

  constructor(
    layoutCalculator: TimelineLayoutCalculator,
    onSceneSelect: (sceneId: string | null) => void,
    onSceneReorder: (fromIndex: number, toIndex: number) => void,
    setDragState: (state: DragState) => void
  ) {
    this.layoutCalculator = layoutCalculator
    this.onSceneSelect = onSceneSelect
    this.onSceneReorder = onSceneReorder
    this.setDragState = setDragState
  }

  /**
   * 更新内部状态
   */
  updateState(viewport: ViewportState, sceneBlocks: SceneBlockData[]): void {
    this.viewport = viewport
    this.sceneBlocks = sceneBlocks
  }

  /**
   * 鼠标按下事件
   */
  handleMouseDown(event: MouseEvent): void {
    const rect = (event.target as HTMLElement).getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top

    this.isMouseDown = true
    this.dragStartPosition = { x, y }

    // 检查是否点击了场景块
    const hitBlock = this.layoutCalculator.hitTest(x, y, this.sceneBlocks)
    
    if (hitBlock) {
      // 选中场景
      this.onSceneSelect(hitBlock.scene.id)
      
      // 准备可能的拖拽操作
      this.setDragState({
        isDragging: false,
        draggedSceneId: hitBlock.scene.id,
        dragStartX: x,
        dragCurrentX: x,
        insertIndex: -1,
        originalIndex: this.findSceneIndex(hitBlock.scene.id)
      })
    } else {
      // 点击空白区域，取消选择
      this.onSceneSelect(null)
      this.setDragState({
        isDragging: false,
        draggedSceneId: null,
        dragStartX: 0,
        dragCurrentX: 0,
        insertIndex: -1,
        originalIndex: -1
      })
    }
  }

  /**
   * 鼠标移动事件
   */
  handleMouseMove(event: MouseEvent): void {
    if (!this.isMouseDown) return

    const rect = (event.target as HTMLElement).getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top

    // 检查是否开始拖拽
    const distance = Math.sqrt(
      Math.pow(x - this.dragStartPosition.x, 2) + 
      Math.pow(y - this.dragStartPosition.y, 2)
    )

    if (distance > this.dragThreshold) {
      this.startDragging(x)
    }
  }

  /**
   * 鼠标释放事件
   */
  handleMouseUp(event: MouseEvent): void {
    if (!this.isMouseDown) return

    this.isMouseDown = false

    // 获取当前拖拽状态
    this.getCurrentDragState((dragState) => {
      if (dragState.isDragging && dragState.insertIndex >= 0) {
        // 执行重排序
        this.onSceneReorder(dragState.originalIndex, dragState.insertIndex)
      }

      // 重置拖拽状态
      this.setDragState({
        isDragging: false,
        draggedSceneId: null,
        dragStartX: 0,
        dragCurrentX: 0,
        insertIndex: -1,
        originalIndex: -1
      })
    })
  }

  /**
   * 鼠标离开事件
   */
  handleMouseLeave(): void {
    if (this.isMouseDown) {
      this.handleMouseUp({} as MouseEvent)
    }
  }

  /**
   * 开始拖拽
   */
  private startDragging(currentX: number): void {
    this.getCurrentDragState((dragState) => {
      if (dragState.draggedSceneId) {
        const targetTime = this.layoutCalculator.pixelToTime(currentX, this.viewport)
        const insertIndex = this.layoutCalculator.getInsertIndex(
          this.sceneBlocks.map(block => block.scene), 
          targetTime
        )

        this.setDragState({
          ...dragState,
          isDragging: true,
          dragCurrentX: currentX,
          insertIndex
        })
      }
    })
  }

  /**
   * 查找场景索引
   */
  private findSceneIndex(sceneId: string): number {
    return this.sceneBlocks.findIndex(block => block.scene.id === sceneId)
  }

  /**
   * 获取当前拖拽状态的异步方法
   * 这是一个临时解决方案，理想情况下应该通过ref或其他方式获取最新状态
   */
  private getCurrentDragState(callback: (state: DragState) => void): void {
    // 由于React状态更新的异步性，这里使用setTimeout确保获取最新状态
    setTimeout(() => {
      // 这里需要外部提供获取当前状态的方法
      // 暂时使用默认值，实际使用时需要改进
      callback({
        isDragging: false,
        draggedSceneId: null,
        dragStartX: 0,
        dragCurrentX: 0,
        insertIndex: -1,
        originalIndex: -1
      })
    }, 0)
  }

  /**
   * 清理事件监听器
   */
  cleanup(): void {
    // 如果有全局事件监听器，在这里清理
  }
}